#! /usr/bin/env bash

# If we have an error, bail out!
set -e

# If we're debugging, be really loudly verbose
[[ ! -z $DEBUG ]] && set -x

# Attempt to load up the /etc/lsb-release file to determine our OS. If none is
# found, we default our settings to RHEL/Amazon Linux as the original behavior
# of this script intended.
if [[ -f /etc/lsb-release ]]; then
  dist=Ubuntu
elif [[ -f /etc/debian_version ]]; then
  dist=Debian
else
  dist=RedHat
fi

# Tell the user what OS we detected
echo "Detected OS Distro: ${dist}"

# Make sure only root can run our script
if [ "$(id -u)" != "0" ]; then
 echo "This script must be run as root" >&2
 exit 1
fi

# Based on the OS, determine which commands we'll be calling to install/manage
# certain things
case "$dist" in
  Ubuntu)
    install_package="apt-get install -y"
    init_dir=/etc/init.d
    sysconfig_dir=/etc/default ;;
  Debian)
    install_package="apt-get install -y"
    init_dir=/etc/init.d
    sysconfig_dir=/etc/default ;;
  *)
    install_package="yum install -y"
    init_dir=/etc/rc.d/init.d
    sysconfig_dir=/etc/sysconfig ;;
esac

daemon_name=aws-kinesis-agent
agent_user_name=aws-kinesis-agent-user
bin_dir=/usr/bin
cron_dir=/etc/cron.d
config_dir=/etc/aws-kinesis
config_flow_dir=${config_dir}/agent.d
jar_dir=/usr/share/${daemon_name}/lib
dependencies_dir=./dependencies
log_dir=/var/log/${daemon_name}
state_dir=/var/run/${daemon_name}
agent_service=${init_dir}/${daemon_name}

usage() {
  echo "Usage:"
  echo "To install Kinesis Agent, type:"
  echo "  sudo <script-path>/setup --install"
  echo "To uninstall Kinesis Agent, type:"
  echo "  sudo <script-path>/setup --uninstall"
}

fail() {
  echo $1 >&2
  exit 1
}

download_jar() {
  group_id=$1
  artifact_id=$2
  version=$3
  prefix="http://search.maven.org/remotecontent?filepath="
  path=${group_id//.//}
  jar_name=$artifact_id-$version.jar
  tmp_dest=$(mktemp -u)
  jar_dest=$dependencies_dir/$jar_name
  url=${prefix}${path}/${artifact_id}/${version}/${jar_name}
  
  # file exists? then don't download it!
  [[ -f ${jar_dest} ]] && return

  # download the file to a temp location, then if move it here if successful
  echo "Downloading $jar_name ($url)..."
  wget -q -P ${dependencies_dir} $url -O ${tmp_dest} && \
    mv ${tmp_dest} ${jar_dest}

  # Purge our temp file regardless of the status here
  rm -f ${tmp_dest}
}

download_dependencies() {
  which ant > /dev/null || $install_package ant
  which wget > /dev/null || $install_package wget
  
  install -d ${dependencies_dir}
  
  echo "Downloading dependencies ..."
  aws_java_sdk_version="1.11.700"
  
  remote_mvn_pkg="com.amazonaws:aws-java-sdk-core:${aws_java_sdk_version} \
                  com.amazonaws:aws-java-sdk-kinesis:${aws_java_sdk_version} \
                  com.amazonaws:aws-java-sdk-cloudwatch:${aws_java_sdk_version} \
                  com.amazonaws:aws-java-sdk-sts:${aws_java_sdk_version} \
                  com.amazonaws:aws-java-sdk-ec2:${aws_java_sdk_version} \
                  com.fasterxml.jackson.core:jackson-annotations:2.10.3\
                  com.fasterxml.jackson.core:jackson-core:2.10.3 \
                  com.fasterxml.jackson.core:jackson-databind:2.10.5.1 \
                  com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.10.3 \
                  com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.10.3 \
                  com.google.code.findbugs:jsr305:3.0.1 \
                  com.google.guava:guava:29.0-jre \
                  org.apache.httpcomponents:httpclient:4.5.13 \
                  org.apache.httpcomponents:httpclient-cache:4.5.1 \
                  org.apache.httpcomponents:httpmime:4.5.1 \
                  org.apache.httpcomponents:httpcore:4.4.3 \
                  org.apache.httpcomponents:httpcore-ab:4.4.3 \
                  org.apache.httpcomponents:httpcore-nio:4.4.3 \
                  commons-cli:commons-cli:1.2 \
                  commons-codec:commons-codec:1.6 \
                  commons-logging:commons-logging-adapters:1.1 \
                  commons-logging:commons-logging-api:1.1 \
                  org.apache.commons:commons-lang3:3.4 \
                  org.apache.logging.log4j:log4j-1.2-api:2.17.0 \
                  org.apache.logging.log4j:log4j-api:2.17.0 \
                  org.apache.logging.log4j:log4j-core:2.17.0 \
                  org.apache.logging.log4j:log4j-slf4j-impl:2.17.0 \
                  org.slf4j:slf4j-api:1.7.12 \
                  com.beust:jcommander:1.48 \
                  org.xerial:sqlite-jdbc:3.20.1 \
                  joda-time:joda-time:2.8.2 \
                  org.projectlombok:lombok:1.16.6"
  
  for package in ${remote_mvn_pkg}
  do
   download_jar $(echo $package | tr : " ")
  done
}

do_uninstall () {
  echo "Uninstalling $daemon_name ..."
  # stop the service if it's running
  if [ -f $agent_service ]; then
    echo "Stopping $daemon_name..."
    $agent_service stop
  fi

  # remove the service from system services
  echo "Removing $daemon_name from system services..."
  case "$dist" in
    Ubuntu) update-rc.d -f $daemon_name remove > /dev/null 2>&1 || true ;;
    Debian) update-rc.d -f $daemon_name remove > /dev/null 2>&1 || true ;;
    *) chkconfig --del $daemon_name > /dev/null 2>&1 || true ;;
  esac
  
  # remove the jars and config files
  rm -rf ${state_dir}
  rm -rf ${log_dir}
  rm -rf ${jar_dir}
  rm -f ${agent_service}
  rm -f ${bin_dir}/start-${daemon_name}
  
  # remove the user for starting the agent
  userdel $agent_user_name > /dev/null || true
  groupdel $agent_user_name > /dev/null || true
  
  # remove sysconfig
  rm -f ${sysconfig_dir}/${daemon_name}
  
  # remove cron job	
  rm -f ${bin_dir}/${daemon_name}-babysit
  rm -f ${cron_dir}/${daemon_name}

  return 0
}

do_build () {
  download_dependencies
  
  ant || fail "Failed to build the Java project"
}

do_install () {
  do_uninstall
  
  echo "Installing Kinesis Agent ..."
  
  do_build
  
  install -d ${config_dir}
  install -d ${config_flow_dir}
  install -d ${jar_dir}
  install -d ${init_dir}
  install -d ${cron_dir}
  install -d ${sysconfig_dir}
  install -d ${log_dir}
  install -d ${state_dir}
  install -m755 ./bin/start-${daemon_name} ${bin_dir}
  install -m755 ./bin/${daemon_name}-babysit ${bin_dir}
  install -m644 ./${dependencies_dir}/* ${jar_dir}
  install -m644 ./ant_build/lib/* ${jar_dir}
  install -m755 ./bin/${daemon_name}.${dist} ${init_dir}/${daemon_name}
  install -m644 ./support/${daemon_name}.cron ${cron_dir}/${daemon_name}
  install -m644 ./support/${daemon_name}.sysconfig ${sysconfig_dir}/${daemon_name}
  install -m644 ./support/log4j.xml ${config_dir}
  
  # add a user for starting the agent
  id -u $agent_user_name > /dev/null 2>&1 || \
  useradd -c "Streaming Data Agent" -r $agent_user_name
  usermod -L $agent_user_name
  
  # change the owner of log files and checkpoint files to the user
  chown -R $agent_user_name $state_dir
  chown -R $agent_user_name $log_dir
  
  config_file=${config_dir}/agent.json
  [[ -f ${config_file} ]] || install -m644 ./configuration/release/${daemon_name}.json ${config_file}
  echo "Configuration file installed at: ${config_file}"
  echo "Configuration details:"
  cat "${config_file}"
  
  case "$dist" in
    Ubuntu) update-rc.d $daemon_name defaults ;;
    Debian) update-rc.d $daemon_name defaults ;;
    *) chkconfig --add $daemon_name ;;
  esac
  
  echo "Amazon Kinesis Agent is installed successfully."
  echo "To start the $daemon_name service, run:"
  echo "  sudo service $daemon_name start"
  echo "To stop the $daemon_name service, run:"
  echo "  sudo service $daemon_name stop"
  echo "To check the status of the $daemon_name service, run:"
  echo "  sudo service $daemon_name status"
  echo ""
  echo "$daemon_name log file will be found at: $log_dir"
  
  echo "To make the agent automatically start at system startup, type:"
  echo "  sudo chkconfig $daemon_name on"
  echo ""
  echo "Your installation has completed!"
}

COMMAND=$1
case "$COMMAND" in
  --build)
    shift
    do_build "$@"
    ;;
  --install)
    shift
    do_install "$@"
    ;;
  --uninstall)
    shift
    do_uninstall "$@"
    echo "Kinesis Agent has been uninstalled"
    ;;
  *)
    usage
    ;;
esac
